import os

import numpy as np
import pandas as pd

from .SchedulingProblem import SchedulingProblem

MK_Case_path = os.path.join(os.path.dirname(__file__), "LocalData/Benchmark/MK_Case")


class FlexibleJobShopSchedulingProblem(SchedulingProblem):
    def __init__(self):
        super().__init__()

    @classmethod
    def is_valid_file_name(cls, file_name):
        if file_name[-4:] == ".fjs" or file_name[-4:] == ".txt":
            return True
        return False

    @staticmethod
    def load(path):
        file = open(path, 'r', encoding='utf-8')
        first_line_str = file.readline()
        first_line_list = first_line_str.split()
        total_number_of_jobs = int(first_line_list[0])
        total_number_of_machines = int(first_line_list[1])
        average_number_of_selectable_machines_per_process = float(first_line_list[2])

        job_datas = dict()
        job_index = 0
        for line in file.readlines():
            if line == '\n':
                continue
            job_datas[job_index] = dict()
            line_int_list = list(map(int, line.split()))
            job_datas[job_index][0] = line_int_list[0]
            line_int_list.pop(0)
            line_index = 0
            operation_index = 1
            while line_index < len(line_int_list):
                line_index += 1
                job_datas[job_index][operation_index] = dict()
                for _ in range(line_int_list[line_index - 1]):
                    job_datas[job_index][operation_index][
                        line_int_list[line_index]] = \
                        line_int_list[line_index + 1]
                    line_index += 2
                operation_index += 1
            job_index += 1
        problem = FlexibleJobShopSchedulingProblem()
        operations_num = 0

        for jk in job_datas:
            job = job_datas[jk]

            problem.jobs_operation[jk] = np.array([], dtype=np.int32)
            for i in range(1, job[0] + 1):
                problem.operations[operations_num] = pd.Series(job[i])
                problem.jobs_operation[jk]=np.append(problem.jobs_operation[jk],operations_num)
                for mk in job[i]:
                    if mk not in problem.machines_operation.keys():
                        problem.machines_operation[mk] = np.array([], dtype=np.int32)
                    problem.machines_operation[mk] = np.append(problem.machines_operation[mk], operations_num)
                operations_num += 1
        problem.machines_operation = problem.machines_operation.sort_index()
        return problem

    @classmethod
    def load_all(cls, path=None):
        if path is None:
            path = MK_Case_path
        return super().load_all(path)

    def convert_to_file_string(self):
        jobs_str = ""
        for jk in self.jobs_operation.keys():
            jo_list = self.jobs_operation[jk]
            jobs_str += " " + f"{len(jo_list)} "
            for ok in jo_list:
                om = self.operations[ok]
                jobs_str += " " + f"{len(om)}"
                for mk in om.keys():
                    jobs_str += " " + f"{mk}" + " " + f"{om[mk]}"
            jobs_str += "\n"

        return f"{self.total_number_of_jobs} {self.total_number_of_machines}	{self.average_number_of_selectable_machines_per_process}\n" \
            + jobs_str
